#pragma once

#include "funpl.h"
#include "range.h"

namespace funpl
{

namespace parser
{

/// Tokens.
namespace token_type
{
	/// Enumeration.
	enum t
	{
		// Keywords
		kw_fun = 0,
		kw_def,
		kw_var,
		kw_struct,

		kw_module, // context-sensitive?
		kw_import, // context-sensitive?

		kw_namespace,
		kw_using,
		kw_typedef,

		kw_class,
		kw_typegroup,

		kw_if,
		kw_else,
		kw_for,
		kw_while,
		kw_do,

		kw_return,

		kw_in,
		
		kw_new,
		kw_delete,

		kw_throw,
		kw_try,
		kw_catch,
		kw_guard,
		kw_unguard,

		// Tokens
		tok_identifier,
		tok_num_literal,
		tok_char_literal,
		tok_string_literal,

		tok_oparen,
		tok_cparen,
		tok_obrace,
		tok_cbrace,
		tok_obracket,
		tok_cbracket,

		tok_semicolon,
		tok_comma,

		tok_questionmark,
		
		tok_op_colon,

		op_period,

		op_tilde,
		
		op_add,
		op_sub,
		op_mul,
		op_div,
		op_mod,
		
		op_and,
		op_or,
		op_xor,
		op_not,

		op_to,
		op_on,
		
		op_increment,
		op_decrement,
		
		op_logical_and,
		op_logical_or,
		
		op_assign,

		op_add_assign,
		op_sub_assign,
		op_mul_assign,
		op_div_assign,
		op_mod_assign,
		
		op_and_assign,
		op_or_assign,
		op_xor_assign,
		
		op_equal,
		op_not_equal,
		op_less,
		op_less_equal,
		op_greater,
		op_greater_equal,

		unknown = -2,
		end = -1
	};
}

/// Token.
struct token
{
	token_type::t type;				///< Token type.
	util::const_char_range range;	///< Token character range.
	
	/// Constructor.
	token(token_type::t type = token_type::unknown,
		const util::const_char_range &range = util::const_char_range(nullptr, nullptr))
			: type(type),
			range(range) { }
};

/// Gets the type of the given identifier.
token_type::t identifier_token_type(const util::const_char_range &identifier);

/// Gets the type of the given special 1-character range.
token_type::t special_1_token_type(const util::const_char_range &special);
/// Gets the type of the given special 2-character range.
token_type::t special_2_token_type(const util::const_char_range &special);

/// Gets the name of the given token type.
const char* token_type_name(token_type::t type);

} // namespace

} // namespace